use serde_json::{Value, json};

use super::{entity::{TransformerApplication, PipePort, MessagePipe}, gen::GenericResult};

/**
 * @author Dream-Lab مۇختەرجان مەخمۇت
 * @email ug-project@outlook.com
 * @create date 2022-07-20 14:38:44
 * @modify date 2022-07-20 14:38:44
 * @desc [description]
*/

pub trait ToJson {
    fn to_json(&self) -> Value;
}
pub trait FromJson<T> {
    fn from_json(value: &serde_json::Value) -> T;
}

impl ToJson for TransformerApplication {
    fn to_json(&self) -> Value {
        json!({
            "uuid": self.uuid,
            "name": self.name,
            "description": self.description,
            "inputPort": Vec::from_iter(self.input_port.iter().map(|port| port.to_json())),
            "outputPort": Vec::from_iter(self.input_port.iter().map(|port| port.to_json())),
        })
    }
}

impl ToJson for PipePort {
    fn to_json(&self) -> Value {
        json!({
            "pipeId": self.name,
            "name": self.name,
            "useCaseDescription": self.use_case_description,
        })
    }
}
// impl ToJson for MessagePipe {
//     fn to_json(&self) -> Value {
        
//     }
// }

impl FromJson<TransformerApplication> for TransformerApplication {
    fn from_json(value: &serde_json::Value) -> TransformerApplication {
        TransformerApplication {
            uuid: value["uuid"].as_str().unwrap().into(),
            name: value["name"].as_str().unwrap().into(),
            description: value["description"].as_str().unwrap().into(),
            input_port: Vec::from_iter(value["inputPort"].as_array().unwrap().iter().map(|port| PipePort::from_json(port))),
            output_port: Vec::from_iter(value["outputPort"].as_array().unwrap().iter().map(|port| PipePort::from_json(port))),
            is_online: false,
            pending_message_offset: 0
        }
    }
}

impl FromJson<PipePort> for PipePort {
    fn from_json(value: &serde_json::Value) -> PipePort {
        PipePort {
            pipe_id: value["pipeId"].as_str().unwrap().into(),
            name: value["name"].as_str().unwrap().into(),
            use_case_description: value["useCaseDescription"].as_str().unwrap().into(),
        }
    }
}

impl GenericResult {
    pub fn succeed() -> GenericResult {
        GenericResult { succeed: true, message: "Succeed".into() }
    }
    pub fn failed(message: &str) -> GenericResult {
        GenericResult { succeed: false, message: message.into() }
    }
}